<?php
/**
 * 下载类
 *
 * @author fakis738@gmail.com
 * @link http://www.woophp.com/manual/class/files.lib.php
 * @version $id files.lib.php v0.1 2011-12-03$
 */
class Files
{
    var $path       = '';
    var $fileinfo   = array();
    var $childs     = array();
    var $rootpath   = '';

    function __construct()
    {
    }


    /**
     * 设置路径
     * 
     * @access	public
     * @param	string $path 文件或目录路径
     * @return	bool
     */
    function setPath($path = '')
    {
        @clearstatcache();

        $this->rootpath = $this->autoPath(ROOTPATH);
        $this->path = empty($path) ? '.'. DIRECTORY_SEPARATOR : $this->autoPath($path);

        if($fileinfo = $this->getInfo($this->path))
        {
            $this->fileinfo = $fileinfo;
            return TRUE;
        }
        return FALSE;
    }


    /**
     * 自动转换相对路径为Windows或Linux路径符号
     *
     * @access  public
     * @param   string $path 相对路径
     * @return  string
     */
    function autoPath($path)
    {
        $autopath = $path;
        $autopath = str_replace('/', DIRECTORY_SEPARATOR, $autopath);
        $autopath = str_replace('\\', DIRECTORY_SEPARATOR, $autopath);
        $autopath = trim($autopath, DIRECTORY_SEPARATOR);
        return $autopath;
    }


    /**
     * 目录排序
     * 
     * @access	public
     * @param	array $childs
     * @return	array
     */
    function dirSort($dirs, $sort_type = 'name', $sort = SORT_ASC)
    {
        if(!is_array($dirs))
        {
            return FALSE;
        }

        foreach($dirs as $k => $v)
        {
            $dir_type[$k] = $v[$sort_type];
            $type[$k] = $v['type'];
        }

        array_multisort($type, $sort, $dir_type, $sort, $dirs);
        return $dirs;
    }


    /**
     * 读取文件
     *
     * @access	public
     * @param	string $filename 文件名
     * @return	string
     */
    function read($filename = '')
    {
        $filename = empty($filename) ? $this->path : $filename;

        if(!is_file($filename))
        {
            return FALSE;
        }

        if(function_exists('file_get_contents'))
        {
            return file_get_contents($filename);
        }

        if(!$fp = @fopen($filename, 'r'))
        {
            return FALSE;
        }

        $data = '';
        if(filesize($filename) > 0)
        {
            flock($fp, LOCK_SH);
            $data =& fread($fp, filesize($filename));
            flock($fp, LOCK_UN);
        }

        @fclose($fp);

        return $data;
    }


    /**
     * 写入文件，并在没有此文件时新建文件
     *
     * @access	public
     * @param	string $file 文件路径
     * @param	string $data 文件数据
     * @param	string $mode 写入文件模式
     * @return	bool
     */
    function write($filename, $data, $mode = 'wb')
    {
        if(!is_file($filename))
        {
            return FALSE;
        }

        if(!$fp = @fopen($filename, $mode))
        {
            return FALSE;
        }

        if($data)
        {
            flock($fp, LOCK_EX);
            fwrite($fp, $data);
            flock($fp, LOCK_UN);
        }

        @fclose($fp);

        return TRUE;
    }


    /**
     * 返回上级目录绝对路径
     * 
     * @access	public
     * @return	string 上级目录绝对路径
     */
    function parentDir($path = '')
    {
        if(FALSE !== $this->currentDir($path))
        {
            return dirname($this->fileinfo['apath']);
        }
        return FALSE;
    }


    /**
     * 返回当前目录绝对路径
     * 
     * @access	public
     * @return	string 当前目录绝对路径
     */
    function currentDir($path = '')
    {
        if($path)
        {
            if($this->setPath($path) && $this->type == 'dir')
            {
                return $this->fileinfo['apath'];
            }
        }
        else
        {
            if($this->fileinfo['apath'] && $this->type == 'dir')
            {
                return $this->fileinfo['apath'];
            }
        }
        return FALSE;
    }


    /**
     * 返回当前目录下级的文件和目录的集合
     * 
     * @access	public
     * @param	string $type
     * @param	string $path 当前目录绝对路径
     * @return	array
     */
    function childDir($type = 'child', $path = '')
    {
        $path = empty($path) ? $this->path : $path;

        if(!$curDir = @opendir($path))
        {
            return FALSE;
        }
        while(FALSE !== ($filename = @readdir($curDir)))
        {
            if($filename != '.' && $filename != '..' && $filename != '.svn')
            {
                $realpath = $path. DIRECTORY_SEPARATOR. $filename;
                $this->childs[] = $this->getInfo($realpath);
                $this->childs = $this->dirSort($this->childs, 'apath', SORT_ASC);
                if($type == 'all')
                {
                    $this->childDir('all', $realpath);
                }
            }
        }
        return (array)$this->childs;
    }


    /**
     * 循环创建目录
     * 
     * @access	public
     * @param	string $dirname 相对路径 + 目录名
     * @return	bool
     */
    function makeDir($dirname)
    {
        $dirname = str_replace('/', DIRECTORY_SEPARATOR, $dirname);
        $dirname = str_replace('\\', DIRECTORY_SEPARATOR, $dirname);
        $dirname = trim($dirname, DIRECTORY_SEPARATOR);

        $node = explode(DIRECTORY_SEPARATOR, $dirname);
        foreach($node as $val)
        {
            $this->fileinfo['apath'] .= DIRECTORY_SEPARATOR. $val;
            if(!mkdir($this->fileinfo['apath'], 0777))
            {
                return FALSE;
            }
        }

        return TRUE;
    }


    /**
     * 删除文件或目录
     *
     * @access	public
     * @param	string $path 路径
     * @param	bool $delSelf 是否删除自身目录
     * @return	bool
     */
    function delete($path = '', $delSelf = FALSE)
    {
        if($this->childDir('all'))
        {
            $this->childs = $this->dirSort($this->childs, 'path', SORT_DESC);
            foreach($this->childs as $k => $v)
            {
                if($v['type'] === 'file')
                {
                    echo '[unlink]: '. $v['path']. "\n";
                    @unlink($v['path']);
                }
                elseif($v['type'] === 'dir')
                {
                    echo '[rmdir]: '. $v['path']. "\n";
                    @rmdir($v['path']);
                }
            }
            echo '[rmdir]: '. $this->fileifno['apath']. "\n";
            @rmdir($this->fileinfo['apath']);
            return TRUE;
        }
        return FALSE;
    }


    /**
     * 复制文件或目录
     * 
     * @access	public
     * @param	string $path 相对路径
     * @return	bool
     */
    function copy($path)
    {
        if($this->childDir('all'))
        {
            echo '[mkdir]: '. $path. "\n";
            @mkdir($path, 0777);
            $this->childs = $this->dirSort($this->childs, 'path', SORT_ASC);
            foreach($this->childs as $k => $v)
            {
                $rpath = str_replace('D:\\Project\\woophp\\www\\', '', $v['path']);
                if($v['type'] === 'dir')
                {
                    echo '[mkdir]: '. $path. DIRECTORY_SEPARATOR .$rpath. "\n";
                    @mkdir($path. DIRECTORY_SEPARATOR .$rpath, 0777);
                }
                elseif($v['type'] === 'file')
                {
                    echo '[copy]: '. $v['path']. ' [to] '. $path. DIRECTORY_SEPARATOR. $rpath. "\n";
                    @copy($v['path'], $path. DIRECTORY_SEPARATOR. $rpath);
                }
            }
            return TRUE;
        }
        return FALSE;
    }


    /**
     * 移动文件或目录
     * 
     * @access	public
     * @param	string $path 相对路径
     * @return	bool
     */
    function move($path)
    {
        return @rename($this->path, $path);
    }


    /**
     * 获得文件信息
     *
     * @access	public
     * @param	string	$path
     * @param	string|array $returned
     * @return	array
     */
    function getInfo($path, $returned = array('name', 'type', 'rpath', 'apath', 'size', 'mtime'))
    {
        if(!file_exists($path))
        {
            return FALSE;
        }

        if(is_string($returned))
        {
            $returned = explode(',', $returned);
        }

        foreach($returned as $key)
        {
            switch ($key)
            {
            case 'name':
                $fileinfo['name'] = substr(strrchr($path, DIRECTORY_SEPARATOR), 1);
                break;
            case 'type':
                $fileinfo['type'] = filetype($path);
                break;
            case 'rpath':
                $fileinfo['rpath'] = str_replace($this->rootpath. DIRECTORY_SEPARATOR, '.'. DIRECTORY_SEPARATOR, realpath($path));
                break;
            case 'apath':
                $fileinfo['apath'] = realpath($path);
                break;
            case 'size':
                $fileinfo['size'] = filesize($path);
                break;
            case 'mtime':
                $fileinfo['mtime'] = filemtime($path);
                break;
            case 'readable':
                $fileinfo['readable'] = is_readable($path);
                break;
            case 'writable':
                $fileinfo['writable'] = is_writable($path);
                break;
            case 'fileperms':
                $fileinfo['fileperms'] = fileperms($path);
                break;
            }
        }

        return $fileinfo;
    }


    /**
     * Get Mime by Extension
     *
     * Translates a file extension into a mime type based on config/mimes.php.
     * Returns FALSE if it can't determine the type, or open the mime config file
     *
     * Note: this is NOT an accurate way of determining file mime types, and is here strictly as a convenience
     * It should NOT be trusted, and should certainly NOT be used for security
     *
     * @access	public
     * @param	string	path to file
     * @return	mixed
     */
    function get_mime_by_extension($file)
    {
        $extension = strtolower(substr(strrchr($file, '.'), 1));

        global $mimes;

        if ( ! is_array($mimes))
        {
            if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT))
            {
                include(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT);
            }
            elseif (is_file(APPPATH.'config/mimes'.EXT))
            {
                include(APPPATH.'config/mimes'.EXT);
            }

            if ( ! is_array($mimes))
            {
                return FALSE;
            }
        }

        if (array_key_exists($extension, $mimes))
        {
            if (is_array($mimes[$extension]))
            {
                // Multiple mime types, just give the first one
                return current($mimes[$extension]);
            }
            else
            {
                return $mimes[$extension];
            }
        }
        else
        {
            return FALSE;
        }
    }


    /**
     * 获得unix文件权限
     *
     * @access	public
     * @param	int
     * @return	string
     */
    function symbolic_permissions($perms)
    {
        if (($perms & 0xC000) == 0xC000)
        {
            $symbolic = 's'; // Socket
        }
        elseif (($perms & 0xA000) == 0xA000)
        {
            $symbolic = 'l'; // Symbolic Link
        }
        elseif (($perms & 0x8000) == 0x8000)
        {
            $symbolic = '-'; // Regular
        }
        elseif (($perms & 0x6000) == 0x6000)
        {
            $symbolic = 'b'; // Block special
        }
        elseif (($perms & 0x4000) == 0x4000)
        {
            $symbolic = 'd'; // Directory
        }
        elseif (($perms & 0x2000) == 0x2000)
        {
            $symbolic = 'c'; // Character special
        }
        elseif (($perms & 0x1000) == 0x1000)
        {
            $symbolic = 'p'; // FIFO pipe
        }
        else
        {
            $symbolic = 'u'; // Unknown
        }

        // Owner
        $symbolic .= (($perms & 0x0100) ? 'r' : '-');
        $symbolic .= (($perms & 0x0080) ? 'w' : '-');
        $symbolic .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-'));

        // Group
        $symbolic .= (($perms & 0x0020) ? 'r' : '-');
        $symbolic .= (($perms & 0x0010) ? 'w' : '-');
        $symbolic .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-'));

        // World
        $symbolic .= (($perms & 0x0004) ? 'r' : '-');
        $symbolic .= (($perms & 0x0002) ? 'w' : '-');
        $symbolic .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-'));

        return $symbolic;
    }


    /**
     * 获得unix八进制文件权限
     *
     * @access	public
     * @param	int
     * @return	string
     */
    function octal_permissions($perms)
    {
        return substr(sprintf('%o', $perms), -3);
    }

}


